package com.fruit.service.account;

import com.fruit.mapper.account.AccountMapper;
import com.fruit.mapper.account.balance.BalanceDetailMapper;
import com.fruit.mapper.account.transaction.TransactionFlowPoMapper;
import com.fruit.pojo.Page;
import com.fruit.pojo.account.CashApply;
import com.fruit.pojo.account.balance.BalanceDetail;
import com.fruit.pojo.account.transaction.TransactionFlowPo;
import com.fruit.pojo.account.user.UserAccount;
import com.fruit.pojo.pay.TransactionFlow;
import com.fruit.pojo.sms.SmsCodeValidate;
import com.fruit.pojo.user.UserReal;
import com.fruit.sdk.account.AccountManager;
import com.fruit.sdk.account.NoticeManager;
import com.fruit.service.sms.SmsCodeManager;
import com.fruit.util.CustomUtil;
import com.joe.http.client.IHttpClient;
import com.joe.http.request.IHttpGet;
import com.joe.utils.cluster.lock.ClusterLock;
import com.joe.utils.common.BeanUtils;
import com.joe.utils.common.DateUtil;
import com.joe.utils.common.IDCard;
import com.joe.utils.common.StringUtils;
import com.joe.utils.concurrent.LockService;
import com.joe.utils.parse.json.JsonParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author joe
 * @version 2017.12.12 10:06
 */
@Slf4j
public abstract class AbstractAccountService implements AccountManager {
    protected static final Pattern DATEPATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}");
    protected static final DecimalFormat NUMFORMAT = new DecimalFormat("#.00");
    protected static final JsonParser PARSER = JsonParser.getInstance();
    protected static final IHttpClient CLIENT = IHttpClient.builder().build();
    /**
     * 实名认证的APPCODE
     */
    protected static final String APPCODE = "15bb490e012242bdbbb0c2c1ea0e17ff";
    /**
     * 实名认证API的地址
     */
    protected static final String CERTURL = "http://1.api.apistore.cn/idcard";
    @Autowired
    protected AccountMapper accountMapper;
    @Autowired
    protected SmsCodeManager smsCodeManager;
    @Autowired
    protected TransactionFlowPoMapper payMapper;
    @Autowired
    protected BalanceDetailMapper balanceDetailMapper;
    @Resource(type = NoticeService.class)
    protected NoticeManager noticeManager;
    @Autowired(required = false)
    protected LockManager lockService;


    /**
     * 检查身份证是否有人使用
     *
     * @param card 身份证
     * @return true表示有人使用
     */
    protected boolean checkIdCard(String card) {
        return accountMapper.checkIdCard(card) > 0;
    }

    /**
     * 实名认证
     *
     * @param card 身份证号
     * @param name 真实姓名
     * @return 返回true表示实名认证通过，返回false表示拒绝
     */
    protected boolean check(String card, String name) {
        log.debug("开始认证身份证号{}和真实姓名{}是否一致", card, name);
        if (StringUtils.isEmpty(card) || StringUtils.isEmpty(name) || !(card.length() == 15 || card.length() == 18)
                || !IDCard.check(card)) {
            log.warn("身份证号{}格式错误", card);
            return false;
        }
        IHttpGet request = new IHttpGet(CERTURL);
        request.addHeader("Authorization", "APPCODE " + APPCODE);
        try {
            request.addQueryParam("cardNo", URLEncoder.encode(card, "UTF8"));
            request.addQueryParam("realName", URLEncoder.encode(name, "UTF8"));

            String result = CLIENT.execute(request).getResult();
            log.debug("实名认证的结果为：{}", result);
            Map<String, Object> map = PARSER.readAsObject(result, HashMap.class);
            Integer code = (Integer) map.get("error_code");

            if (code == null) {
                log.error("实名认证接口异常，请处理，返回结果为：{}", request);
                return false;
            }
            if (code == 0) {
                Object obj = map.get("result");
                if (obj == null) {
                    log.warn("实名认证接口返回结果不包含result");
                    return false;
                }
                Map<String, Object> resultMap = (Map<String, Object>) obj;
                if ((Integer) resultMap.get("isok") == 1) {
                    return true;
                } else {
                    log.warn("实名认证失败，接口返回：{}", result);
                    return false;
                }
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("实名认证异常，请处理", e);
            return false;
        }
    }

    @Override
    public String getRealName(long uid, boolean blur) {
        if (uid <= 0) {
            return null;
        }
        UserReal userReal = accountMapper.getUserRealByUid(uid);
        if (userReal == null || StringUtils.isEmpty(userReal.getRealName())) {
            return null;
        } else {
            String realName = userReal.getRealName();
            if (blur) {
                return "*" + realName.substring(realName.length() - 1);
            } else {
                return realName;
            }
        }
    }

    /**
     * 申请提现（需要自行验证，调用该方法表示已经验证过，该方法会直接根据信息提现）
     * <p>
     * 注意：该方法需要有事务上下文
     *
     * @param cashApply 提现信息
     * @return 返回true表示提现成功，返回false表示提现失败（用户余额不足）
     */
    protected boolean cashApply(CashApply cashApply) {
        UserAccount account = accountMapper.getUserAccount(cashApply.getUser_id(), true);
        double all = cashApply.getPrice().add(cashApply.getPoundage()).doubleValue();
        if (Double.compare(account.getBalance().doubleValue(), all) < 0) {
            //余额不足
            log.debug("用户钱包余额不足");
            return false;
        }
        //减去手续费和提现金额
        account.setBalance(account.getBalance().subtract(cashApply.getPrice()).subtract(cashApply.getPoundage()));
        log.debug("更新余额为：{}", account);
        //更新余额
        if (accountMapper.updateByUserId(account) <= 0) {
            //更新失败
            log.debug("钱包更新失败");
            return false;
        }
        log.debug("用户余额更新后为：{}", account);
        log.debug("生成流水");
        TransactionFlow transactionFlow = createTransaction(cashApply);
        cashApply.setTransaction_id(transactionFlow.getId());
        //生成明细
        log.debug("生成明细");
        createBalanceDetail(cashApply, account, true);
        log.debug("保存提现记录");
        accountMapper.saveCashApply(cashApply);
        log.info("提现{}记录生成成功", cashApply);
        return true;
    }

    /**
     * 发送短信验证码
     *
     * @param uid  用户ID
     * @param type 验证码类型
     * @return 发送结果
     */
    protected Map<String, Object> sendSms(long uid, String type) {
        log.debug("给用户{}发送{}类型的验证码", uid, type);
        String phone = noticeManager.getUserPhone(uid);
        if (StringUtils.isEmpty(phone)) {
            log.warn("用户{}没有手机号", uid);
            Map<String, Object> map = new HashMap<>();
            map.put("message", "用户没有绑定手机号");
            return map;
        }

        log.debug("给手机{}发送{}类型的验证码", phone, type);
        SmsCodeValidate sms = new SmsCodeValidate();
        sms.setPhone(phone);
        sms.setTypes(type);
        Map<String, Object> map = smsCodeManager.sendSmsCode(sms);
        log.debug("手机{}的{}类型的验证码发送结果为：{}", phone, type, map);
        //移除里边的验证码
        map.remove("code");
        return map;
    }

    /**
     * 检验验证码的正确性
     *
     * @param phone 手机号
     * @param type  验证码类型
     * @param code  验证码
     * @return 返回0表示验证码正确，1表示验证码失效，2表示系统异常或者验证码错误
     */
    protected int validateCode(String phone, String type, String code) {
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(type) || StringUtils.isEmpty(code)) {
            return 2;
        }
        String status = smsCodeManager.getValidateCode(phone, code, type);

        if ("ok".equals(status)) {
            return 0;
        } else if ("expire".equals(status)) {
            return 1;
        }
        return 2;
    }

    /**
     * 根据提现生成流水并保存
     *
     * @param cashApply 提现详情
     * @return 生成的流水（已经保存）
     */
    protected TransactionFlow createTransaction(CashApply cashApply) {
        log.debug("开始生成流水");
        BigDecimal all = cashApply.getPrice().add(cashApply.getPoundage());
        String time = DateUtil.getFormatDate("yyyy-MM-dd HH:mm:ss");

        TransactionFlow transactionFlow = new TransactionFlow();
        transactionFlow.setUserId((int) cashApply.getUser_id());
        transactionFlow.setTotalPrice(all);
        transactionFlow.setPayPrice(all);
        transactionFlow.setPriceState("02");
        transactionFlow.setRemark("余额提现");
        transactionFlow.setState("01");
        transactionFlow.setType("03");
        transactionFlow.setCreateTime(DateUtil.getFormatDate(time));
        transactionFlow.setFinishTime(time);
        TransactionFlowPo tfp = BeanUtils.copy(transactionFlow, TransactionFlowPo.class);
        payMapper.insertTransactionFlows(Collections.singletonList(tfp));
        log.debug("生成的流水为：{}", tfp);
        transactionFlow.setCode(CustomUtil.orderCode(3, tfp.getId(), tfp.getUserId()));
        tfp.setCode(CustomUtil.orderCode(3, tfp.getId(), tfp.getUserId()));
        transactionFlow.setId(tfp.getId());
        payMapper.updateCode(tfp);
        log.debug("流水生成完毕");
        return transactionFlow;
    }

    /**
     * 生成交易明细并保存（该方法已经保存）
     *
     * @param cashApply 提现申请
     * @param account   用户账户（更新后的账户，主要使用余额）
     * @param add       拒绝提现还是申请提现，false为拒绝提现，true为提现申请
     * @return 交易明细
     */
    protected BalanceDetail createBalanceDetail(CashApply cashApply, UserAccount account, boolean add) {
        log.debug("根据提现申请{}和用户账户{}生成交易明细", cashApply, account);
        BalanceDetail balanceDetail = new BalanceDetail();
        BigDecimal all = cashApply.getPoundage().add(cashApply.getPrice());
        balanceDetail.setUserId((int) cashApply.getUser_id());
        balanceDetail.setMoney(all);
        balanceDetail.setTransactionId(cashApply.getTransaction_id());
        balanceDetail.setType("02");
        balanceDetail.setCreateTime(DateUtil.getFormatDate("yyyy-MM-dd HH:mm:ss"));
        balanceDetail.setUpdateTime(balanceDetail.getCreateTime());
        balanceDetail.setCurBalance(account.getBalance());

        if (add) {
            //同意提现
            balanceDetail.setRemark("提现申请");
            balanceDetail.setIncomeState("00");
        } else {
            //拒绝提现
            balanceDetail.setRemark("拒绝提现");
            balanceDetail.setIncomeState("01");
        }
        balanceDetailMapper.insertBalanceDetails(Collections.singletonList(balanceDetail));
        log.info("交易明细保存成功，明细为：{}", balanceDetail);
        return balanceDetail;
    }

    /**
     * 查询指定月份账单
     *
     * @param date   指定月份，格式为：yyyy-MM，传入空值或者不传表示查询所有
     * @param uid    用户id
     * @param pageNo 分页页码，从0开始
     * @param size   分页大小
     * @return 指定月份账单
     */
    protected Page<Commission> getBill(String date, long uid, int pageNo, int size) {
        log.info("用户{}查找[{}]的账单", uid, date);
        Page<Commission> page = new Page<>();
        List<TransactionFlow> transactionFlows = accountMapper.getCommissionDetails(uid, date, pageNo * size, size
                + 1);
        log.debug("用户{}在{}的账单为：{}", uid, date, transactionFlows);

        page.setPageNo(pageNo);
        //判断是否是空
        if (transactionFlows.isEmpty()) {
            page.setData(Collections.emptyList());
            return page;
        }

        //判断是否有下一页
        if (transactionFlows.size() == size + 1) {
            transactionFlows.remove(size);
            page.setHasNext(true);
        }

        page.setData(transactionFlows.stream().map(transactionFlow -> {
            Commission commission = convert(transactionFlow);
            if ("00".equals(transactionFlow.getType()) && "02".equals(transactionFlow.getState())) {
                commission.setState("交易关闭");
            } else if ("03".equals(transactionFlow.getType())) {
                if ("01".equals(transactionFlow.getState())) {
                    commission.setState("处理中");
                } else if ("03".equals(transactionFlow.getState())) {
//                    commission.setState("提现成功");
                    commission.setState(null);
                } else {
                    commission.setState(null);
                }
            } else {
                commission.setState(null);
            }
            return commission;
        }).collect(Collectors.toList()));
        log.debug("用户{}在{}的账单详情为：{}", uid, date, page);
        return page;
    }

    /**
     * 查询指定月份余额明细
     *
     * @param date   指定月份，格式为：yyyy-MM，传入空值或者不传表示查询所有
     * @param uid    用户id
     * @param pageNo 分页页码，从0开始
     * @param size   分页大小
     * @return 指定月份余额明细
     */
    protected Page<Commission> getDetail(String date, long uid, int pageNo, int size) {
        log.info("用户{}查找[{}]的余额明细", uid, date);
        Page<Commission> page = new Page<>();
        List<BalanceDetail> balanceDetails = accountMapper.getBalanceDetails(uid, date, pageNo * size, size
                + 1);
        log.debug("用户{}在{}的余额明细为：{}", uid, date, balanceDetails);

        page.setPageNo(pageNo);
        //判断是否是空
        if (balanceDetails.isEmpty()) {
            page.setData(Collections.emptyList());
            return page;
        }

        //判断是否有下一页
        if (balanceDetails.size() == size + 1) {
            balanceDetails.remove(size);
            page.setHasNext(true);
        }

        page.setData(balanceDetails.stream().map(this::convert).collect(Collectors.toList()));
        log.debug("用户{}在{}的余额明细为：{}", uid, date, page);
        return page;
    }

    /**
     * 将系统流水转换为相应的账单（获取账单列表和获取账单详情都会调用该方法）
     *
     * @param transactionFlow 系统数据库流水
     * @return 相应的账单
     */
    protected Commission convert(TransactionFlow transactionFlow) {
        Class<? extends Commission> clazz = typeResolve(transactionFlow.getType());
        if (clazz == null) {
            return null;
        }
        Commission commission = BeanUtils.copy(transactionFlow, clazz);
        if ("02".equals(transactionFlow.getPriceState())) {
            //与余额明细中的状态保持一致
            commission.setPriceState("00");
        }
        //类型不同，必须手动处理
        commission.setUserId((long) transactionFlow.getUserId());
        commission.setTotalPrice(dealDouble(transactionFlow.getTotalPrice()));
        deal(commission);
        return commission;
    }

    /**
     * 将余额明细转换为相应的前端展示数据
     *
     * @param balanceDetail 数据库余额明细
     * @return 前端展示的数据
     */
    protected Commission convert(BalanceDetail balanceDetail) {
        Commission commission = BeanUtils.copy(balanceDetail, Commission.class);
        //预处理，处理标题等
        deal(commission);
        dealDetail(commission, balanceDetail);
        return commission;
    }

    /**
     * 处理账单中的标题、备注、类型以及详细信息
     *
     * @param commission 要处理的账单
     */
    protected void deal(final Commission commission) {
        //是否是明细，为true表示是明细，false表示是账单详情
        boolean isDetail = false;
        if (Commission.class.equals(commission.getClass())) {
            //只有这种情况是获取明细而不是账单详情
            isDetail = true;
        }
        //判断当前钱包状态是增加还是减少
        boolean add = "01".equals(commission.getPriceState());
        commission.setTypePrint(typeConvert(commission.getType(), isDetail, add));
        commission.setRemark(remarkConvert(commission.getType(), commission.getRemark(), isDetail));
        commission.setTitle(titleConvert(commission.getType(), commission.getRemark(), isDetail, add));
    }

    /**
     * 处理余额明细
     *
     * @param commission    余额明细
     * @param balanceDetail 余额明细数据实体
     */
    protected void dealDetail(Commission commission, BalanceDetail balanceDetail) {
        //下列两个字段在流水表中名字不一样，无法被BeanUtils的copy方法复制，所以需要特殊处理一下
        commission.setTotalPrice(dealDouble(balanceDetail.getMoney()));
        commission.setPriceState(balanceDetail.getIncomeState());
        commission.setBalance(dealDouble(balanceDetail.getCurBalance()));
        TransactionFlow transactionFlow = accountMapper.getTransactionFlow(balanceDetail.getTransactionId());
        if (transactionFlow != null) {
            commission.setCode(transactionFlow.getCode());
        }
    }

    /**
     * 处理提现详情
     *
     * @param cashOut 要处理的提现详情
     */
    protected void dealCashOut(final AccountManager.CashOut cashOut) {
        CashApply cashApply = accountMapper.getCashout(cashOut.getId(), true);
        if (cashApply == null) {
            log.warn("找不到提现详情{}对应的提现申请", cashOut);
            return;
        }
        cashOut.setPoundage(dealDouble(cashApply.getPoundage()));
        String state = cashApply.getState();
        if ("00".equals(state)) {
            cashOut.setStatus("审核中");
            cashOut.setDescript("正在审核");
        } else if ("01".equals(state)) {
            cashOut.setStatus("通过");
            cashOut.setDescript("提现成功");
        } else if ("02".equals(state)) {
            cashOut.setStatus("拒绝");
            cashOut.setDescript("提现审核失败");
        } else {
            log.warn("审核状态{}不存在", state);
        }

        cashOut.setPoundage("-" + cashOut.getPoundage());

        if ("01".equals(cashApply.getCash_mode())) {
            //支付宝
            String account = cashApply.getAlipay_account();
            cashOut.setAccount("支付宝(" + account.substring(0, 3) + "****" + account.substring(account.length() - 4)
                    + ")");
        } else {
            //银行卡
            String card = cashApply.getBank_card();
            cashOut.setAccount(cashApply.getBank_name() + "(" + card.substring(0, 4) + "****" + card.substring(card
                    .length() - 4) + ")");
        }
    }

    /**
     * 处理返现详情
     *
     * @param cashBack 要处理的返现详情
     */
    protected void dealCashBack(final AccountManager.CashBack cashBack) {
        if (cashBack.getUserId() == null) {
            log.warn("cashback[{}]的用户ID为null", cashBack);
        }
        //设置邀请的好友的昵称
        cashBack.setFriend(accountMapper.getFriend(cashBack.getId()));
        cashBack.setDescript("交易成功");
        cashBack.setPayCompany("果犇农业科技（北京）有限公司");
    }

    /**
     * 处理消费详情
     *
     * @param consume 要处理的消费详情
     * @param state   消费状态
     */
    protected void dealConsume(final AccountManager.Consume consume, String state) {
        //消费账单暂时不需要处理
        if ("alipay".equals(consume.getPayMode())) {
            consume.setPayMode("支付宝");
        } else if ("wechat".equals(consume.getPayMode())) {
            consume.setPayMode("微信");
        }
        switch (state) {
            case "00":
                consume.setDescript("支付失败");
                break;
            case "01":
                consume.setDescript("支付成功");
                break;
            case "02":
                consume.setDescript("支付失败");
                break;
            default:
                throw new IllegalArgumentException("没有状态：" + state);
        }
    }

    /**
     * 类型转换，将账单详情的系统类型转换为前台显示的类型
     *
     * @param type     系统类型，例如01,02
     * @param isDetail 是否是明细，为true表示是明细，false表示是账单详情
     * @param add      钱包是增加还是减少，true表示增加
     * @return 前台显示的类型，示例：获取佣金-一级
     */
    protected String typeConvert(String type, boolean isDetail, boolean add) {
        if (isDetail) {
            //余额明细
            switch (type) {
                case "01":
                    return "消费支出";
                case "02":
                    return "余额提现";
                case "03":
                    return "账户奖励";
                case "04":
                    if (add) {
                        return "账户奖励";
                    } else {
                        return "推荐支出";
                    }
                default:
                    log.error("流水类型{}未知", type);
                    return null;
            }
        } else {
            //账单详情
            switch (type) {
                case "00":
                    return "消费";
                case "01":
                    return "充值";
                case "02":
                    return "账户奖励";
                case "03":
                    return "余额提现";
                case "04":
                    if (add) {
                        return "账户奖励";
                    } else {
                        return "推荐支出";
                    }
                default:
                    log.error("账单类型{}未知", type);
                    return null;
            }
        }

    }

    /**
     * 转换备注，将账单中的后台系统备注转换为前台显示的备注
     *
     * @param type     类型
     * @param remark   后台系统备注，例如01、02
     * @param isDetail 是否是明细，为true表示是明细，false表示是账单详情
     * @return 前台显示的备注，例如：邀请好友获取佣金
     */
    protected String remarkConvert(String type, String remark, boolean isDetail) {
        //备注暂时不用转换
        return remark;
    }

    /**
     * 根据后台的账单类型和备注生成前台的标题
     *
     * @param type     后台的佣金类型，例如：01、02
     * @param remark   后台的备注，例如：01、02
     * @param isDetail 是否是明细，为true表示是明细，false表示是账单详情
     * @param add      钱包是增加还是减少，true表示增加
     * @return 前台显示的标题，例如：获取一级佣金，当在账单详情使用时是金额下方的说明，例如：领取成功、付款成功、审核中
     */
    protected String titleConvert(String type, String remark, boolean isDetail, boolean add) {
        if (isDetail) {
            //如果是明细那么列表页标题和类型一致
            return typeConvert(type, isDetail, add);
        } else {
            //如果是账单那么列表页标题和remark一致
            return remark;
        }
    }

    /**
     * 将数据库的状态转换为系统当前的状态（数据库状态可能会变，该方法相当于一个映射，反映射
     * 参考{@link #stateConvert(int)}）
     *
     * @param state 数据库的状态
     * @return 系统状态（其中返回1表示未申请认证，返回2表示申请认证未审核，返回3表示实名认证审核未通过，返回4表示实
     * 名认证审核已通过，返回5表示未知状态）
     */
    protected int stateConvert(String state) {
        if (StringUtils.isEmpty(state)) {
            return 5;
        }
        //判断属于什么状态
        switch (state) {
            case "01":
                return 2;
            case "02":
                return 4;
            case "03":
                return 3;
            default:
                log.error("实名认证状态异常，该状态为：{}", state);
                return 5;
        }
    }

    /**
     * 根据数据库的流水类型确定返回的类型
     *
     * @param type 数据库的流水类型
     * @return 要返回的实体类型
     */
    protected Class<? extends Commission> typeResolve(String type) {
        if (type == null) {
            log.error("要确定的类型为空");
            return null;
        }
        switch (type) {
            case "00":
                return AccountManager.Consume.class;
            case "01":
                log.warn("当前没有充值记录");
                return null;
            case "02":
                return AccountManager.CashBack.class;
            case "03":
                return AccountManager.CashOut.class;
            case "04":
                return AccountManager.Spread.class;
            default:
                log.error("类型{}未知", type);
                return null;
        }
    }

    /**
     * 将系统状态转换为数据库实名认证审核状态
     *
     * @param state 系统中的实名认证审核状态（系统中1表示未申请认证，2表示申请认证未审核，3表示实名认证审核未通过，4表
     *              示实名认证审核已通过，5表示未知状态）
     * @return 对应的数据库中的审核状态
     */
    protected String stateConvert(int state) {
        switch (state) {
            case 1:
                return null;
            case 2:
                return "01";
            case 3:
                return "03";
            case 4:
                return "02";
            default:
                throw new RuntimeException("系统实名认证状态中没有状态：" + state);
        }
    }

    /**
     * 将BigDecimal做保留小数点后两位处理，不足的补零（四舍五入）
     *
     * @param bigDecimal bigDecimal
     * @return 处理后的字符串
     */
    protected static String dealDouble(BigDecimal bigDecimal) {
        double count = bigDecimal.doubleValue();
        if (count < 0.005 && count > -0.005) {
            return "0.00";
        }
        String result = NUMFORMAT.format(count);
        return result.startsWith(".") ? "0" + result : result;
    }

    /**
     * 加锁
     *
     * @param lockName 锁名
     */
    protected void lock(String lockName) {
        log.debug("锁定{}", lockName);
        ClusterLock clusterLock;
        if (lockService == null || (clusterLock = lockService.getLock(lockName)) == null) {
            log.warn("当前分布式锁不可用");
            Lock lock = LockService.getLock(lockName);
            lock.lock();
            log.debug("锁定{}成功", lockName);
        } else {
            log.debug("当前分布式锁可用，使用分布式锁锁定{}", lockName);
            clusterLock.lock();
            log.debug("锁定{}成功", lockName);
        }
    }

    /**
     * 解锁
     *
     * @param lockName 锁名
     */
    protected void unlock(String lockName) {
        log.debug("解锁{}", lockName);
        ClusterLock clusterLock;
        if (lockService == null || (clusterLock = lockService.getLock(lockName)) == null) {
            log.debug("当前分布式锁不可用");
            Lock lock = LockService.getLock(lockName);
            lock.unlock();
            log.debug("解锁{}成功", lockName);
        } else {
            log.debug("当前分布式锁可用，解锁{}", lockName);
            clusterLock.unlock();
            log.debug("解锁{}成功", lockName);
        }
    }
}
